#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <string.h>
#include <sys/poll.h>

#define MAXNUM 1024

int serverFd;
int r=0;
int epfd;

void hand(int s)
{
    if (2==s)
    {
        //close 断开链接
        printf("bye bye\n");
        close(epfd);
        close(serverFd);
        exit(1);
    }
}


void init()
{

    //创建socket
    serverFd = socket(AF_INET,SOCK_STREAM,0);
    if (-1==serverFd)
    {
        printf("创建socket失败\n");
        exit(-1);
    }
    printf("创建socket成功\n");

    //协议地址簇
    struct sockaddr_in addr={0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");//ip地址 注意字符串转网络字节序
    addr.sin_port=htons(4556);


    //绑定
    r = bind(serverFd,( struct sockaddr*)&addr,sizeof addr);

    if (-1==r)
    {
        printf("绑定失败:%m\n");
        close(serverFd);
        exit(-1);
    }
    printf("绑定成功\n");

    //监听
    r = listen(serverFd,100);
    if (-1==r)
    {
        printf("监听失败:%m\n");
        close(serverFd);
        exit(-1);
    }
    printf("监听成功\n");

}



int main(){
    signal(2,hand);
    init();

    epfd = epoll_create(MAXNUM);
    if (-1==epfd)
    {
        printf("创建epoll失败：%m\n");
        close(serverFd);
        exit(-1);
    }

    printf("创建epoll成功\n");

    struct epoll_event ev; //注册用
    ev.events = EPOLLIN;
    ev.data.fd = serverFd;

    r = epoll_ctl(epfd,EPOLL_CTL_ADD,serverFd,&ev);
    if (-1==r)
    {
        printf("创建epoll_ctl失败:%m\n");
        hand(2);
        exit(-1);
    }
    printf("创建epoll_ctl成功\n");




    struct epoll_event evs[MAXNUM]; //处理时候用

    int nfds; //epoll_wait 返回值 数量
    char buff[1024];
    while (1)
    {
        nfds = epoll_wait(epfd,evs,MAXNUM,0);
        if (nfds<0)
        {
            printf("epoll_wait失败：%m\n");
            hand(2);
            exit(-1);
        }else if (nfds==0)
        {
            //printf("没动静\n");
            continue;
        }else
        {
            for (int i=0;i<nfds;i++)
            {
                if (serverFd==evs[i].data.fd)
                {

                    int cfd = accept(serverFd,NULL,NULL);
                    if (-1==cfd)
                     {
                        printf("服务器崩溃：%m\n");
                        hand(2);
                    }
                    printf("有客户端连接服务器:%d\n",cfd);
                    //注册客户端的描述符号监视
                    ev.events = EPOLLIN;
                    ev.data.fd = cfd;
                    epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);
                }else if (evs[i].events&EPOLLIN)
                {
                    int curCfd = evs[i].data.fd;
                    printf("客户端发数据过来了:%d\n",curCfd);

                    int len = recv(curCfd,buff,1023,0);
                    if (len>0)
                    {
                        buff[len]=0;
                        printf("%d>>%s\n",curCfd,buff);
                    }else
                    {
                        printf("断开链接：%d\n",curCfd);
                        ev.events = EPOLLIN;
                        ev.data.fd = curCfd;
                        epoll_ctl(epfd,EPOLL_CTL_DEL,curCfd,&ev);
                    }
                }
            }
        }
    }



}
